
/***
 * @Description: 基于不同的硬件平台需要配置适合各自的网卡收发数据包线程的C语言文件
 * @Author: Liverpool
 * @Date: 2024-01-23 00:18:16
 * @LastEditTime: 2024-01-23 00:21:54
 * @LastEditors: Liverpool
 */
#include "net_interface_pcap.h"
#include "pcap.h"
#include "debug.h"
#include "ethernet.h"
/***
 * @description: 网卡配置的接收数据包线程
 * @Author: Liverpool
 * @Date: 2024-01-23 00:28:02
 * @return {*}
 * @param {void} *arg
 */
void receive_thread(void *arg)
{
    plat_printf("receive threading is running....\n");
    D_Net_Interface *netif = (D_Net_Interface *)arg;
    pcap_t *pcap = (pcap_t *)netif->operation_data;
    while (1)
    {
        struct pcap_pkthdr *pkthdr;                      // 接收到的数据包的相应信息
        const uint8_t *pkt_data;                         // 存储接收到的数据包的内存地址
        if (pcap_next_ex(pcap, &pkthdr, &pkt_data) != 1) // 从网卡接收数据包
        {
            continue;
        }
        D_Packet *buf = packet_alloc(pkthdr->len); // 分配得到相应大小的数据包
        if (buf == (D_Packet *)0)
        {
            debug_Warning(Debug_NetInterface, "packet = NULL");
            continue;
        }
        packet_write(buf, (uint8_t *)pkt_data, pkthdr->len);
        if (net_interface_put_in(netif, buf, 0) < 0) // 向网卡的输入队列写入数据包
        {
            // 如果写入失败，需要释放数据包
            debug_Warning(Debug_NetInterface, "netif:%s inqueue is full", netif->name);
            packet_free(buf);
            continue;
        }
    }
}

/***
 * @description: 网卡配置的发送数据包线程
 * @Author: Liverpool
 * @Date: 2024-01-23 00:29:12
 * @return {*}
 * @param {void} *arg
 */
void send_thread(void *arg)
{
    plat_printf("send threading is running....\n");
    D_Net_Interface *netif = (D_Net_Interface *)arg;
    pcap_t *pcap = (pcap_t *)netif->operation_data;
    static uint8_t rw_buffer[ETHERNET_MTU + 6 + 6 + 2]; // 用来存储以太网的输出队列中的数据
    while (1)
    {
        D_Packet *buf = net_interface_get_out(netif, 0); // 可以等待输出队列的数据
        if (buf == (D_Packet *)0)
        {
            continue;
        }
        int total_size = buf->total_size;
        plat_memset(rw_buffer, 0, sizeof(rw_buffer)); // 清空缓存
        packet_read(buf, rw_buffer, total_size);
        packet_free(buf);
        if (pcap_inject(pcap, rw_buffer, total_size) == -1) // 发送数据包
        {
            // 发送失败
            debug_error(Debug_NetInterface, "pcap send failed:%s", pcap_geterr(pcap));
            debug_error(Debug_NetInterface, "pcap send failed,size = %d", total_size);
        }
    }
}

// 定义网络接口的相关硬件操作
/***
 * @description: (内部静态函数)网卡接口的打开
 * @Author: Liverpool
 * @Date: 2024-04-28 00:27:58
 * @return {*} 打开网卡过程中的错误
 * @param {_Net_Interface} *netif 需要打开的网卡内存地址
 * @param {void} *data 进行操作的数据
 */
static net_interface_pcap_open(struct _Net_Interface *netif, void *data)
{
    D_Pcap_Data *dev_data = (D_Pcap_Data *)data;                     // 进行数据转化
    pcap_t *pcap = pcap_device_open(dev_data->ip, dev_data->hwaddr); // 打开pcap接口
    if (pcap == (pcap_t *)0)
    {
        debug_error(Debug_NetInterface, "pcap open failed! name:%s", netif->name);
        return NET_ERR_IO;
    }
    netif->type = NET_Interface_ETHER; // 设置网卡为以太网类型
    netif->mtu = ETHERNET_MTU;
    netif->operation_data = pcap;                         // pcapa接口进行保存
    net_interface_set_HWaddr(netif, dev_data->hwaddr, 6); // 配置硬件地址

    sys_thread_t recv_thread = sys_thread_create(receive_thread, netif);
    sys_thread_t sendThread = sys_thread_create(send_thread, netif);
    // 创建的线程不合法那就返回协议栈系统错误
    if (recv_thread == SYS_THREAD_INVALID || sendThread == SYS_THREAD_INVALID)
    {
        return NET_ERR_SYS;
    }
    return NET_ERR_OK;
}
/***
 * @description: （内部静态函数）网卡接口的关闭
 * @Author: Liverpool
 * @Date: 2024-04-28 00:27:58
 * @return {*} 关闭网卡过程中的错误
 * @param {_Net_Interface} *netif 需要关闭的网卡内存地址
 */
static void net_interface_pcap_close(struct _Net_Interface *netif)
{
    pcap_t *pcap = (pcap_t *)netif->operation_data;
    pcap_close(pcap);
}
/***
 * @description: （内部静态函数）网卡接口的数据传输
 * @Author: Liverpool
 * @Date: 2024-04-28 00:27:58
 * @return {*} 传输数据中网卡出现的错误
 * @param {_Net_Interface} *netif 需要进行传输的网卡内存地址
 */
static net_err_t net_interface_pcap_transmit(struct _Net_Interface *netif)
{
    return NET_ERR_OK;
}

const D_Net_Interface_operation netdev_opreation = {
    .open = net_interface_pcap_open,
    .close = net_interface_pcap_close,
    .transmit = net_interface_pcap_transmit,
};